package com.yanqu.road.server.gameplayer.module.musicroom;

import com.yanqu.road.dao.impl.player.UserMusicRoomAppraiseDaoImpl;
import com.yanqu.road.dao.impl.player.UserMusicRoomBeautyDaoImpl;
import com.yanqu.road.dao.impl.player.UserMusicRoomBuildingDaoImpl;
import com.yanqu.road.entity.config.badge.BadgeConfig;
import com.yanqu.road.entity.config.beauty.BeautyInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.musicroom.MusicRoomBuildBaseConfig;
import com.yanqu.road.entity.config.musicroom.MusicRoomFurnitureConfig;
import com.yanqu.road.entity.config.musicroom.MusicRoomMissionConfig;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.config.skin.SkinInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.*;
import com.yanqu.road.entity.musicroom.*;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.entity.player.UserSkin;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.activity.MusicRoomProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.*;
import com.yanqu.road.server.gameplayer.module.skin.SkinModule;
import com.yanqu.road.server.gameplayer.module.task.TaskModule;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.maidian.musicroom.MusicRoomLog;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.MusicRoomPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class MusicRoomModule extends GeneralModule {
    public MusicRoomModule(GamePlayer player) {
        super(player);
    }

    private Map<Integer, UserMusicRoomBuildingData> buildingDataMap = new ConcurrentHashMap<>();
    private Map<Integer, UserMusicRoomBeautyData> beautyDataMap = new ConcurrentHashMap<>();
    //key 评价id
    private Map<Integer, UserMusicRoomAppraiseData> appraiseDataMap = new ConcurrentHashMap<>();
    private AtomicInteger maxAppraiseID = new AtomicInteger(1);
    private Random random = new Random();

    @Override
    public boolean loadData() {
        buildingDataMap = new UserMusicRoomBuildingDaoImpl().getUserMusicRoomBuildingData(getUserId());
        beautyDataMap = new UserMusicRoomBeautyDaoImpl().getUserMusicRoomBeautyData(getUserId());
        List<UserMusicRoomAppraiseData> appraiseDataList = new UserMusicRoomAppraiseDaoImpl().getUserMusicRoomAppraiseData(getUserId());
        Map<Integer, UserMusicRoomAppraiseData> tempAppraiseDataMap = new ConcurrentHashMap<>();
        int tempMaxAppraiseId = 0;
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataList) {
            if (appraiseData.getAppraiseId() > tempMaxAppraiseId){
                tempMaxAppraiseId = appraiseData.getAppraiseId();
            }
            tempAppraiseDataMap.put(appraiseData.getAppraiseId(), appraiseData);
        }
        appraiseDataMap = tempAppraiseDataMap;
        maxAppraiseID.set(tempMaxAppraiseId + 1);
        return true;
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public boolean saveData() {
        List<UserMusicRoomBuildingData> buildingDataList = new ArrayList<>();
        synchronized (buildingDataMap) {
            buildingDataList.addAll(buildingDataMap.values());
        }
        for (UserMusicRoomBuildingData buildingData : buildingDataList) {
            if (buildingData.isInsertOption()) {
                new UserMusicRoomBuildingDaoImpl().add(buildingData);
            } else if (buildingData.isUpdateOption()) {
                new UserMusicRoomBuildingDaoImpl().update(buildingData);
            }
        }

        List<UserMusicRoomBeautyData> beautyDataList = new ArrayList<>();
        synchronized (beautyDataMap) {
            beautyDataList.addAll(beautyDataMap.values());
        }
        for (UserMusicRoomBeautyData beautyData : beautyDataList) {
            if (beautyData.isInsertOption()) {
                new UserMusicRoomBeautyDaoImpl().add(beautyData);
            } else if (beautyData.isUpdateOption()) {
                new UserMusicRoomBeautyDaoImpl().update(beautyData);
            }
        }

        List<UserMusicRoomAppraiseData> appraiseDataList = new ArrayList<>();
        synchronized (appraiseDataMap) {
            appraiseDataList.addAll(appraiseDataMap.values());
        }
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataList) {
            if (appraiseData.isInsertOption()) {
                new UserMusicRoomAppraiseDaoImpl().add(appraiseData);
            } else if (appraiseData.isUpdateOption()) {
                new UserMusicRoomAppraiseDaoImpl().update(appraiseData);
            }
        }

        return true;
    }

    @Override
    public void afterLogin() {
        if (!isSystemOpen()) {
            return;
        }
        initUserData();
        initCheckInBuildingBeauty();

        buildingAttrChange();
        calcBeautyRouting();
        settleTimerReward();

        syncBeautyData(new ArrayList<>(beautyDataMap.values()));
        syncAppraiseList(new ArrayList<>(appraiseDataMap.values()));

//        isForceChangeToLifeRouting = checkBuildingAttrChangeRoutingToLife();

        player.getModule(BeautyModule.class).checkAllBeautyMusicRoomSkill();
    }

    public void initSystem() {
        if (!isSystemOpen()) {
            return;
        }
        initUserData();
        player.getModule(BeautyModule.class).checkAllBeautyMusicRoomSkill();

        player.getModule(TaskModule.class).addMusicRoomUnlockTask();
    }

    /**
     * 更新美女和建筑的关系
     */
    public void initCheckInBuildingBeauty() {
        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            buildingData.clearNowBeautyIds();
            buildingData.clearWaitBeautyIds();
        }

        for (UserMusicRoomBeautyData beautyData : beautyDataMap.values()) {
            int nowBuildingId = beautyData.getNowBuildingId();
            UserMusicRoomBuildingData buildingData = buildingDataMap.get(nowBuildingId);
            if (buildingData != null) {
                buildingData.addNowBeautyId(beautyData.getBeautyId());
            }
            UserMusicRoomBuildingData nextBuildingData = buildingDataMap.get(beautyData.getNextBuildingId());
            if (nextBuildingData != null) {
                nextBuildingData.addWaitCheckInBeautyId(beautyData.getBeautyId());
            }
        }
    }

    public boolean isSystemOpen() {
        return SystemOpenMgr.systemOpen(player, eSystemId.MusicRoom.getValue());
    }

    private void initUserData() {
        boolean needTrace = false;

        //初始解锁建筑
        List<Integer> unlockBuildingList = MusicRoomConfigMgr.getUnlockBuildingList(1);
        for (Integer buildId : unlockBuildingList) {
            MusicRoomBuildBaseConfig buildBaseConfig = MusicRoomConfigMgr.getBuildBaseConfig(buildId);
            if (buildBaseConfig == null) {
                continue;
            }
            Property buildingUnlockCost = MusicRoomConfigMgr.getBuildingUnlockCost(buildId);
            if (!buildingUnlockCost.isNothing()) {//有消耗的不解锁
                continue;
            }
            UserMusicRoomBuildingData buildingData = buildingDataMap.get(buildId);
            if (buildingData == null) {
                buildingData = new UserMusicRoomBuildingData(getUserId(), buildId);
                int furnitureNum = buildBaseConfig.getFurnitureNumLimit();
                for (int i = 1; i <= furnitureNum; i++) {
                    MusicRoomFurnitureInfo furnitureInfo = new MusicRoomFurnitureInfo(i);
                    if (MusicRoomConfigMgr.isInitUnlockFurniture(buildId, furnitureInfo.getId())) {
                        furnitureInfo.setLevel(1);

                        player.notifyListener(eGamePlayerEventType.MusicRoomFurnitureLevel.getValue());
                    } else {
                        furnitureInfo.setLevel(0);
                    }
                    buildingData.addFurnitureInfo(furnitureInfo);
                }
                synchronized (buildingDataMap) {
                    buildingDataMap.put(buildId, buildingData);
                }
                needTrace = true;
            }
        }

        if (needTrace) {
            buildingAttrChange();
        }

        long badgeLevel = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        if (0 == badgeLevel) {
            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomBadgeLevel, 1);
            badgeLevel = 1;
            //赚速变更
            player.getModule(EarnSpeedModule.class).scheduleAddSilver();
            //初始的时辰累计奖励
//            Property initTimerReward = MusicRoomConfigMgr.getBadgePerTimerReward((int)badgeLevel, GameConfig.MUSIC_ROOM_PRODUCE_SUPPORTS_INIT_TIMER_AMOUNT);
            Property initTimerReward = new Property();
            long initTimerAmount = GameConfig.MUSIC_ROOM_PRODUCE_SUPPORTS_INIT_TIMER_AMOUNT;
            long prosperity = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);
            long rewardPerTime = getRewardSupportGoodsPerTime(); //每时辰产出的应援币

            if (rewardPerTime > 0) {
                Property timerProduce = new Property(GameConfig.MUSIC_ROOM_SUPPORT_GOODS_ID, rewardPerTime * initTimerAmount);
                initTimerReward.addProperty(timerProduce);
            }
            player.getModule(PlayerModule.class).getUserHistoryAttribute().setMusicRoomTimerAmountReward(initTimerReward);

            BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), (int) badgeLevel);
            if (badgeConfig != null) {
                player.getModule(BadgeModule.class).addBadge(badgeConfig.getId(), eBadgeType.MusicRoom.getValue());
            }


            Property systemReward = SystemOpenMgr.getSystemOpenInfo(eSystemId.MusicRoom.getValue()).getReward();
            if (!systemReward.isNothing() && !player.getModule(CurrencyModule.class).currencyIsEnough(systemReward)) {//背包里没有足够的物品，就给一份初始奖励
                player.getModule(CurrencyModule.class).addCurrency(systemReward, eLogMoneyType.MusicRoom, eLogMoneyType.SystemOpen);
            }

            needTrace = true;
        }

        if (needTrace) {
            MusicRoomLog.trackUserData(player);

            player.notifyListener(eGamePlayerEventType.MusicRoomBuildingUnlock.getValue());
        }

        resetOneDayByHour();
    }

    /**
     * 在妙音坊内，会存在特有的十二时辰。
     * 一时辰对应了现实时间的2分钟
     * 所有的美女，在每个时辰都会根据行程表，前往对应的区域进行表演。
     */
    public synchronized void calcBeautyRouting() {
        long currentTime = DateHelper.getCurrentTime();
        long nowTimeNumberStartTime = MusicRoomConfigMgr.getNowTimeNumberStartTime();
        long lastCheckTime = 0;
        //计算一下产出,美女行程,更新建筑里的美女
        List<UserMusicRoomBeautyData> beautyDataList = getSortLivingBeautyList();
        if (beautyDataList.isEmpty()) {
            return;
        }

        for (UserMusicRoomBeautyData beautyData : beautyDataList) {
            lastCheckTime = beautyData.getLastTimerEndTime();
        }

        //离上次检查时间过去了多少时辰
        long passTimerAmount = (nowTimeNumberStartTime - lastCheckTime) / GameConfig.MUSIC_ROOM_HOUR_REALITY_TIME / DateHelper.SECOND_MILLIONS;
        if (passTimerAmount == 0) {
            return;
        }

        //根据累计轮次上限获得最多累计时辰
        long maxTimerAmount = GameConfig.MUSIC_ROOM_BEAUTY_MAX_SCHEDULE_AMOUNT * GameConfig.MUSIC_ROOM_ALL_TIME_NUMBER;
        if (passTimerAmount > maxTimerAmount) {
            passTimerAmount = maxTimerAmount;
        }

        int timeNumberByTime = MusicRoomConfigMgr.getTimeNumberByTime(lastCheckTime);

        //获得美女行程结果
        MusicRoomRoutingResult calcResult = MusicRoomConfigMgr.calcBeautyRouting(beautyDataList, buildingDataMap, (int) passTimerAmount, timeNumberByTime);

        //结果赋值
        for (MusicRoomRoutingBeauty routingBeauty : calcResult.getBeautyMap().values()) {
            UserMusicRoomBeautyData beautyData = beautyDataMap.get(routingBeauty.getBeautyId());
            beautyData.setComfort(routingBeauty.getComfort());
            beautyData.setMood(routingBeauty.getMood());
            beautyData.setSatiety(routingBeauty.getSatiety());
            beautyData.setScheduleListType(routingBeauty.getScheduleListType());
            beautyData.setScheduleList(routingBeauty.getScheduleList());
            beautyData.setNowBuildingId(routingBeauty.getNowBuildingId());
            beautyData.setNextBuildingId(routingBeauty.getNextBuildingId());
        }

        for (MusicRoomRoutingBuilding routingBuilding : calcResult.getBuildingMap().values()) {
            UserMusicRoomBuildingData buildingData = buildingDataMap.get(routingBuilding.getBuildId());
            buildingData.addAmountReward(routingBuilding.getAmountReward());
            buildingData.setWaitCheckInBeautyIds(routingBuilding.getWaitCheckInBeautyIds());
            buildingData.setNowCheckInBeautyIds(routingBuilding.getNowCheckInBeautyIds());
//            buildingData.addBeautySettleTimes(routingBuilding.getBeautySettleTimes());
        }

        //更新结算时间
        for (UserMusicRoomBeautyData beautyData : beautyDataList) {
            beautyData.setLastTimerEndTime(nowTimeNumberStartTime);
        }
        syncBeautyData(beautyDataList);
    }

    public void sendMainScene() {
        //计算一下产出,美女行程,更新建筑里的美女
        calcBeautyRouting();
        settleTimerReward();

        //发包
        int nowTimeNumber = MusicRoomConfigMgr.getNowTimeNumber();
        MusicRoomProto.MusicRoomMainSceneRespMsg.Builder respMsg = MusicRoomProto.MusicRoomMainSceneRespMsg.newBuilder();
        respMsg.setTimeNumber(nowTimeNumber);
        respMsg.setNextTimeNumberTime(MusicRoomConfigMgr.getNextTimeNumberTime());
        Property timerAmountReward = player.getModule(PlayerModule.class).getUserHistoryAttribute().getMusicRoomTimerAmountReward();
        respMsg.setTimerAmountReward(PropertyHelper.parsePropertyToString(timerAmountReward));

        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            MusicRoomProto.MusicRoomBuildingTemp.Builder buildingTemp = MusicRoomProto.MusicRoomBuildingTemp.newBuilder();
            buildingTemp.setBuildId(buildingData.getBuildId());
            buildingTemp.addAllBeautyId(buildingData.getNowCheckInBeautyIds());
            buildingTemp.setAmountReward(PropertyHelper.parsePropertyToString(buildingData.getAmountReward()));
            for (MusicRoomFurnitureInfo furnitureInfo : buildingData.getFurnitureInfos()) {
                MusicRoomProto.MusicRoomFurnitureTemp.Builder furnitureTemp = MusicRoomProto.MusicRoomFurnitureTemp.newBuilder();
                furnitureTemp.setFurnitureId(furnitureInfo.getId());
                furnitureTemp.setLevel(furnitureInfo.getLevel());
                buildingTemp.addFurniture(furnitureTemp);
            }
            respMsg.addBuildData(buildingTemp);
        }

        respMsg.addAllBeautyRouting(MusicRoomPb.parseBeautyRoutingTempList(new ArrayList<>(beautyDataMap.values())));
        respMsg.setGuideData(player.getModule(PlayerModule.class).getUserHistoryAttribute().getMusicRoomGuide());

        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_MAIN_SCENE, respMsg);
    }

    public void syncBeautyData(List<UserMusicRoomBeautyData> beautyDataList) {
        MusicRoomProto.MusicRoomBeautySyncMsg.Builder syncMsg = MusicRoomProto.MusicRoomBeautySyncMsg.newBuilder();
        for (UserMusicRoomBeautyData beautyData : beautyDataList) {
            MusicRoomProto.MusicRoomBeautyTemp.Builder builder = MusicRoomPb.parseBeautyTemp(beautyData);
            syncMsg.addBeautyData(builder);
        }
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BEAUTY_SYNC, syncMsg);
    }

    /**
     * 解锁建筑
     *
     * @param buildId
     * @return
     */
    public int unlockBuilding(int buildId) {
        if (!isSystemOpen()) {
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        if (buildingDataMap.containsKey(buildId)) {
            return GameErrorCode.E_MUSIC_ROOM_BUILDING_WAS_UNLOCKED;
        }

        MusicRoomBuildBaseConfig buildBaseConfig = MusicRoomConfigMgr.getBuildBaseConfig(buildId);
        if (buildBaseConfig == null) {
            return GameErrorCode.E_MUSIC_ROOM_CONFIG_ERROR;
        }

        int badgeLevel = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), badgeLevel);
        if (badgeConfig == null) {
            return GameErrorCode.E_BADGE_NOT_EXIST;
        }
        if (!MusicRoomConfigMgr.canUnlockBuilding(badgeLevel, buildId)) {
            return GameErrorCode.E_MUSIC_ROOM_BUILDING_UNLOCK_NOT_ENOUGH;
        }

        Property buildingUnlockCost = MusicRoomConfigMgr.getBuildingUnlockCost(buildId);
        if (!buildingUnlockCost.isNothing()) {
            if (!player.getModule(CurrencyModule.class).removeCurrency(buildingUnlockCost, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomBuildingUnlockCost)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
        }
        int buildType = MusicRoomConfigMgr.getBuildType(buildId);

        UserMusicRoomBuildingData buildingData = new UserMusicRoomBuildingData(getUserId(), buildId);
        int furnitureNum = buildBaseConfig.getFurnitureNumLimit();
        for (int i = 1; i <= furnitureNum; i++) {
            MusicRoomFurnitureInfo furnitureInfo = new MusicRoomFurnitureInfo(i);

            if (MusicRoomConfigMgr.isInitUnlockFurniture(buildId, furnitureInfo.getId())) {
                furnitureInfo.setLevel(1);

                player.notifyListener(eGamePlayerEventType.MusicRoomFurnitureLevel.getValue());
            } else {
                furnitureInfo.setLevel(0);
            }

            buildingData.addFurnitureInfo(furnitureInfo);
        }
        synchronized (buildingDataMap) {
            buildingDataMap.put(buildId, buildingData);
        }

        //计算繁荣度
        buildingAttrChange();


        MusicRoomProto.MusicRoomBuildingUnlockRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBuildingUnlockRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setBuildData(MusicRoomPb.parseBuildingTemp(buildingData));
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BUILDING_UNLOCK, respMsg);

        AutoLogMgr.add(new LogMusicRoomBuildingUnlock(getUserId(), buildId));

        MusicRoomLog.trackUserData(player);

        player.notifyListener(eGamePlayerEventType.MusicRoomBuildingUnlock.getValue());
        return 0;
    }

    /**
     * 建筑属性变更,计算总繁荣度,更新总产出
     */
    public void buildingAttrChange() {
        long oldValue = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);
        long totalProsperity = 0;
        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            int buildType = MusicRoomConfigMgr.getBuildType(buildingData.getBuildId());
            int totalFurnitureLevel = 0;
            List<List<Property>> totalProduceExpBookList = new ArrayList<>();
            List<List<Property>> totalProduceSupportItemList = new ArrayList<>();
            long totalSupportMoney = 0;

            for (MusicRoomFurnitureInfo furnitureInfo : buildingData.getFurnitureInfos()) {
                MusicRoomFurnitureConfig furnitureConfig = MusicRoomConfigMgr.getFurnitureConfig(furnitureInfo.getLevel());
                if (furnitureConfig == null) {
                    continue;
                }
                totalFurnitureLevel += furnitureInfo.getLevel();
                long prosperity = furnitureConfig.getProsperity();
                totalProsperity += prosperity;

                if (MusicRoomConfigMgr.isFurnitureProduceExpBook(buildType, furnitureInfo.getId())) {
                    List<List<Property>> produceExpBookList = furnitureConfig.getProduceExpBooksList(buildingData.getBuildId());
                    totalProduceExpBookList.addAll(produceExpBookList);
                }

                if (MusicRoomConfigMgr.isFurnitureProduceSupportItem(buildType, furnitureInfo.getId())) {
                    List<List<Property>> produceSupportItemList = furnitureConfig.getProduceSupportItemsList(buildingData.getBuildId());
                    totalProduceSupportItemList.addAll(produceSupportItemList);
                }

                totalSupportMoney += furnitureConfig.getGold();
            }

            buildingData.setTotalFurnitureLevel(totalFurnitureLevel);
            buildingData.setProduceExpBookList(totalProduceExpBookList);
            buildingData.setProduceSupportItemList(totalProduceSupportItemList);
            buildingData.setSupportMoneyAmount(totalSupportMoney);
        }

        if (totalProsperity != oldValue) {
            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomTotalProsperity, totalProsperity);
            long badgeLevel = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
            RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(totalProsperity), eRankType.MusicRoomRank.getValue(), String.valueOf(badgeLevel));
        }

        //需求变更,繁荣度等级提升时不替换评价
//        long lastRewardTime = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomLastTimerRewardTime);
//        if (lastRewardTime != 0 && oldValue != totalProsperity) {
//            //判断下繁荣度等级有没有升级
//            MusicRoomFurnitureConfig levelConfig = MusicRoomConfigMgr.getFurnitureConfigByProsperity(totalProsperity);
//            if (levelConfig !=null && levelConfig.getNeedProsperity() > oldValue) {
//                //替换评价
//                replaceAppraiseList();
//            }
//        }
    }

    public void settleTimerReward() {
        MusicRoomTimerAmountResult amountResult = calcTotalTimerReward();
        if (amountResult.getTimerAmount() > 0) {
            player.getModule(PlayerModule.class).getUserHistoryAttribute().addMusicRoomTimerAmountReward(amountResult.getTotalReward());
            long lastRewardTime = MusicRoomConfigMgr.getNowRewardTime();
            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomLastTimerRewardTime, lastRewardTime);
            player.getModule(AttributeModule.class).addAttribute(ePlayerAttrType.MusicRoomRewardAmountTime, amountResult.getTimerAmount());
        }
    }

    /**
     * 计算建筑累计奖励
     */
    public MusicRoomTimerAmountResult calcBuildingAmountReward() {
        MusicRoomTimerAmountResult result = new MusicRoomTimerAmountResult();
        Property totalReward = new Property();

        int timerSeconds = GameConfig.MUSIC_ROOM_OUTPUT_TIME; //每时辰秒数
        int maxTimerAmount = GameConfig.MUSIC_ROOM_PRODUCE_SUPPORTS_MAX_TIMER_AMOUNT;//最大累计时辰数
        long lastRewardTime = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomLastTimerRewardTime);//上一次领奖时间,毫秒

        long nowTime = System.currentTimeMillis();
        int timerAmount = 0;
        if (lastRewardTime > 0) {//初始为0不算奖励
            timerAmount = (int) ((nowTime - lastRewardTime) / (timerSeconds * 1000)); //累计时辰数
            if (timerAmount > maxTimerAmount) {
                timerAmount = maxTimerAmount;
            }
            if (timerAmount > 0) {
                Property totalSupportMoney = new Property();
                for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
                    for (int i = 0; i < timerAmount; i++) {
                        Property expBookProduce = PropertyHelper.randomPropertyByListList(buildingData.getProduceExpBookList());
                        Property supportProduce = PropertyHelper.randomPropertyByListList(buildingData.getProduceSupportItemList());
                        if (buildingData.getSupportMoneyAmount() > 0) {
                            Property supportMoney = new Property(GameConfig.MUSIC_ROOM_SUPPORT_GOODS_ID, buildingData.getSupportMoneyAmount());
                            totalSupportMoney.addProperty(supportMoney);
                        }
                        totalReward.addProperty(expBookProduce);
                        totalReward.addProperty(supportProduce);
                    }
                }
                totalSupportMoney.goodMulti(getGoodAppraiseBigDecimalAddition(), BigDecimal.ROUND_DOWN);
                totalReward.addProperty(totalSupportMoney);
            }
        }

        result.setTotalReward(totalReward);
        result.setTimerAmount(timerAmount);

        return result;
    }

    /**
     * 领取建筑累计奖励
     */
    public MusicRoomProto.MusicRoomGetBuildingRewardRespMsg.Builder getBuildingAmountReward() {
        MusicRoomProto.MusicRoomGetBuildingRewardRespMsg.Builder respMsg = MusicRoomProto.MusicRoomGetBuildingRewardRespMsg.newBuilder();
        if (!SystemOpenMgr.systemOpen(player, eSystemId.MusicRoom.getValue())) {
            return respMsg.setRet(GameErrorCode.E_SYSTEM_NO_OPEN);
        }

        //功能型建筑奖励,徽章表配置
        int badgeLevel = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), badgeLevel);
        if (badgeConfig == null) {
            return respMsg.setRet(GameErrorCode.E_BADGE_NOT_EXIST);
        }
        settleTimerReward();
        Property totalReward = player.getModule(PlayerModule.class).getUserHistoryAttribute().getMusicRoomTimerAmountReward();
        //更新上一次领奖时间为跨时辰的时间
        long showPassTime = 0; //给客户端用的领奖过去了多久毫秒
        long lastRewardTimeOld = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomLastTimerRewardGetTime);
        if (lastRewardTimeOld == 0) {
            lastRewardTimeOld = MusicRoomConfigMgr.getNowRewardTime();
            showPassTime = GameConfig.MUSIC_ROOM_PRODUCE_SUPPORTS_INIT_TIMER_AMOUNT * GameConfig.MUSIC_ROOM_OUTPUT_TIME * DateHelper.SECOND_MILLIONS;
        }else{
            showPassTime = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomRewardAmountTime) * GameConfig.MUSIC_ROOM_OUTPUT_TIME * DateHelper.SECOND_MILLIONS;
        }
        long lastRewardTimeNew = MusicRoomConfigMgr.getNowRewardTime();
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomLastTimerRewardGetTime, lastRewardTimeNew);
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomLastTimerRewardTime, lastRewardTimeNew);
        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomRewardAmountTime, 0);

        player.getModule(PlayerModule.class).getUserHistoryAttribute().setMusicRoomTimerAmountReward(new Property()); //清空累计奖励

        if (!totalReward.isNothing()) {
            player.getModule(CurrencyModule.class).addCurrency(totalReward, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomBuildingAmountReward);
        }else{
            return respMsg.setRet(GameErrorCode.E_MUSIC_ROOM_NO_BUILDING_AMOUNT_REWARD);
        }


        respMsg.setRet(0);
        respMsg.setReward(PropertyHelper.parsePropertyToString(totalReward));
        respMsg.setGetTimePass(showPassTime);

        long passAmount = (showPassTime) / (GameConfig.MUSIC_ROOM_OUTPUT_TIME * DateHelper.SECOND_MILLIONS);

        AutoLogMgr.add(new LogMusicRoomGetAmountReward(player.getUserId(), lastRewardTimeOld, lastRewardTimeNew, (int) passAmount, respMsg.getReward()));

        return respMsg;
    }

    /**
     * 家具升级
     */
    public int furnitureUpgrade(int buildId, int furnitureId, int lvUpNum) {
        if (lvUpNum <= 0) {
            return GameErrorCode.E_ERROR_DATA;
        }
        //升级前先更新结算一下行程
        calcBeautyRouting();
        settleTimerReward();
        if (lvUpNum == 0) {
            lvUpNum = 1;
        }

        if (!buildingDataMap.containsKey(buildId)) {
            return GameErrorCode.E_MUSIC_ROOM_BUILDING_NOT_UNLOCK;
        }

        MusicRoomBuildBaseConfig buildBaseConfig = MusicRoomConfigMgr.getBuildBaseConfig(buildId);
        if (buildBaseConfig == null) {
            return GameErrorCode.E_MUSIC_ROOM_CONFIG_ERROR;
        }
        int maxLevel = buildBaseConfig.getFurnitureMaxLevel();

        UserMusicRoomBuildingData buildingData = buildingDataMap.get(buildId);
        Property cost = new Property();

        List<MusicRoomProto.MusicRoomFurnitureTemp> resultFurnitureMsgList = new ArrayList<>();

        if (furnitureId == 0) {//传的家具id为0时,表示全部家具一起升级，能升多少级就升多少级
            Map<MusicRoomFurnitureInfo, Integer> furnitureEndLevelMap = new HashMap<>();
            for (MusicRoomFurnitureInfo furnitureInfo : buildingData.getFurnitureInfos()) {
                int endLevel = furnitureInfo.getLevel();
                for (int i = 0; i < lvUpNum; i++) {
                    MusicRoomFurnitureConfig nextLevelConfig = MusicRoomConfigMgr.getFurnitureConfig(furnitureInfo.getLevel() + i + 1);
                    if (nextLevelConfig == null) {
                        break;
                    }
                    Property lvUpCost = nextLevelConfig.getCost(buildId);
                    Property nowCost = new Property(cost);
                    nowCost.addProperty(lvUpCost);

                    if (!player.getModule(CurrencyModule.class).currencyIsEnough(nowCost)) {
                        player.notifyListener(eGamePlayerEventType.RechargeMusicRoom.getValue(), 0);
                        return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                    }

                    cost.addProperty(lvUpCost);

                    endLevel = furnitureInfo.getLevel() + i + 1;
                }

                if (endLevel != furnitureInfo.getLevel()){
                    furnitureEndLevelMap.put(furnitureInfo, endLevel);
                }
            }

            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomFurnitureUpCost)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }

            for (Map.Entry<MusicRoomFurnitureInfo, Integer> entry : furnitureEndLevelMap.entrySet()) {
                MusicRoomFurnitureInfo furnitureInfo = entry.getKey();
                Integer endLevel = entry.getValue();
                furnitureInfo.setLevel(endLevel);
                MusicRoomProto.MusicRoomFurnitureTemp.Builder furnitureTemp = MusicRoomPb.parseFurnitureTemp(furnitureInfo);
                resultFurnitureMsgList.add(furnitureTemp.build());
            }
        }else {
            MusicRoomFurnitureInfo furnitureInfo = buildingData.getFurnitureInfo(furnitureId);
            if (furnitureInfo == null) {
                return GameErrorCode.E_MUSIC_ROOM_FURNITURE_NOT_EXIST;
            }

            if (furnitureInfo.getLevel() + lvUpNum > maxLevel) {
                return GameErrorCode.E_MUSIC_ROOM_FURNITURE_LEVEL_FULL;
            }


            for (int i = 0; i < lvUpNum; i++) {
                MusicRoomFurnitureConfig nextLevelConfig = MusicRoomConfigMgr.getFurnitureConfig(furnitureInfo.getLevel() + i + 1);
                if (nextLevelConfig == null) {
                    return GameErrorCode.E_MUSIC_ROOM_FURNITURE_LEVEL_FULL;
                }
                Property lvUpCost = nextLevelConfig.getCost(buildId);
                cost.addProperty(lvUpCost);
            }

            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomFurnitureUpCost)) {
                player.notifyListener(eGamePlayerEventType.RechargeMusicRoom.getValue(), 0);
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }

            furnitureInfo.setLevel(furnitureInfo.getLevel() + lvUpNum);

            MusicRoomProto.MusicRoomFurnitureTemp.Builder furnitureTemp = MusicRoomPb.parseFurnitureTemp(furnitureInfo);
            resultFurnitureMsgList.add(furnitureTemp.build());
        }

        if (resultFurnitureMsgList.isEmpty()){
            return GameErrorCode.E_MUSIC_ROOM_NO_FURNITURE_CAN_UP;
        }


        buildingData.setUpdateOption();

        buildingAttrChange();

        for (MusicRoomProto.MusicRoomFurnitureTemp furnitureTemp : resultFurnitureMsgList) {
            UserMusicRoomAppraiseData appraiseData = findAppraiseDataByFurnitureId(buildId, furnitureTemp.getFurnitureId());
            if (appraiseData != null && appraiseData.getStatus() == 2) {//检查有没有差评变好评
                if (furnitureTemp.getLevel() >= appraiseData.getTargetLevel()) {
                    appraiseData.setNewStatus(1);//新状态改成好评
                    syncAppraiseList(Collections.singletonList(appraiseData));
                }
            }

            AutoLogMgr.add(new LogMusicRoomFurnitureUp(getUserId(), MusicRoomConfigMgr.getFurnitureUniqueId(buildId, furnitureTemp.getFurnitureId()), furnitureTemp.getLevel()));
        }

        MusicRoomProto.MusicRoomFurnitureUpgradeRespMsg.Builder respMsg = MusicRoomProto.MusicRoomFurnitureUpgradeRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setBuildId(buildId);
        respMsg.addAllFurniture(resultFurnitureMsgList);

        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BUILDING_FURNITURE_UP, respMsg);

        //成就更新
        player.notifyListener(eGamePlayerEventType.MusicRoomFurnitureLevel.getValue());

        MusicRoomLog.trackUserData(player);
        return 0;
    }

    /**
     * 妙音坊 演出
     */
    public int stageBeautyShow(List<Integer> beautyIds) {
        int passStageId = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomStageId);
        int nowStageId = passStageId + 1;
        if (passStageId == 0) {
            nowStageId = MusicRoomConfigMgr.getFirstStageId();
        }

        MusicRoomMissionConfig stageConfig = MusicRoomConfigMgr.getStageConfig(nowStageId);
        if (stageConfig == null) {
            return GameErrorCode.E_MUSIC_ROOM_STAGE_NOT_EXIST;
        }

        if (beautyIds.isEmpty() || beautyIds.size() > stageConfig.getBattleNum()) {
            return GameErrorCode.E_MUSIC_ROOM_SHOW_BEAUTY_NUM_ERROR;
        }

        Set<Integer> beautyIdCheckSet = new HashSet<>();
        Property totalAttr = new Property();
        for (Integer beautyId : beautyIds) {
            if (!beautyDataMap.containsKey(beautyId)) {
                return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_FOUND;
            }
            if (beautyIdCheckSet.contains(beautyId)) {
                return GameErrorCode.E_MUSIC_ROOM_SHOW_BEAUTY_REPEAT;
            }

            beautyIdCheckSet.add(beautyId);

            UserMusicRoomBeautyData beautyData = beautyDataMap.get(beautyId);
            if (beautyData.getLiveInBuildId() == 0) {
                return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_LIVE_IN;
            }

            totalAttr.addProperty(1, beautyData.getAttr1());
            totalAttr.addProperty(2, beautyData.getAttr2());
            totalAttr.addProperty(3, beautyData.getAttr3());
            totalAttr.addProperty(4, beautyData.getAttr4());
            totalAttr.addProperty(5, beautyData.getAttr5());
        }

        Property needAttributeProperty = stageConfig.getNeedAttributeProperty();
        for (Map.Entry<Integer, BigInteger> entry : totalAttr.getGoods().entrySet()) {
            Integer attrType = entry.getKey();
            int attrValue = entry.getValue().intValue();
            int needValue = needAttributeProperty.getCountByGoodsId(attrType).intValue();
            if (attrValue < needValue) {
                //属性不足
                player.notifyListener(eGamePlayerEventType.RechargeMusicRoom.getValue(), 0);
                return GameErrorCode.E_MUSIC_ROOM_SHOW_ATTR_NOT_ENOUGH;
            }
        }

        Property reward = PropertyHelper.randomPropertyByListList(stageConfig.getRewardsPropertyList());
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomStageReward);

        MusicRoomProto.MusicRoomStageShowRespMsg.Builder respMsg = MusicRoomProto.MusicRoomStageShowRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNewStageId(nowStageId);
        respMsg.setReward(PropertyHelper.parsePropertyToString(reward));
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_STAGE_SHOW, respMsg);

        player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomStageId, nowStageId);

        //成就更新
        player.notifyListener(eGamePlayerEventType.MusicRoomMission.getValue());

        AutoLogMgr.add(new LogMusicRoomMission(getUserId(), nowStageId, beautyIds, PropertyHelper.parsePropertyToString(totalAttr), respMsg.getReward()));
        return 0;
    }

    /**
     * 妙音坊 美女换皮肤
     */
    public int beautySwapSkin(int beautyId, int skinId) {
        checkAndNewBeautyData(beautyId);
        if (!beautyDataMap.containsKey(beautyId)) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_FOUND;
        }
        UserMusicRoomBeautyData beautyData = beautyDataMap.get(beautyId);
        if (beautyData.getNowSkin() == skinId) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_SWAP_SKIN_SAME;
        }

        if (skinId != 0) {
            UserSkin userSkin = player.getModule(SkinModule.class).getUserSkin(skinId);
            if (userSkin == null) {
                return GameErrorCode.E_SKIN_NOT_EXIST;
            }
            SkinInfo skinInfo = SkinMgr.getSkinInfo(skinId);
            if (skinInfo == null) {
                return GameErrorCode.E_SKIN_NOT_EXIST;
            }
            // 判断皮肤类型
            if (eSkinType.Beauty.getValue() != skinInfo.getType()) {
                return GameErrorCode.E_SKIN_TYPE_ERROR;
            }

            // 判断美女皮肤归属
            if (skinInfo.getBelongRole() != beautyId) {
                return GameErrorCode.E_SKIN_IS_NOT_BELONG_TO_BEAUTY;
            }
        }

        beautyData.setNowSkin(skinId);
        beautyData.setModifyTime(System.currentTimeMillis());

        syncBeautyData(Collections.singletonList(beautyData));

        MusicRoomProto.MusicRoomBeautySkinUnlockRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBeautySkinUnlockRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setBeautyId(beautyId);
        respMsg.setSkinId(skinId);
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BEAUTY_SKIN_UNLOCK, respMsg);

        return 0;
    }

    /**
     * 妙音坊 解锁拥有的所有皮肤
     */
    public int unlockBeautyAllSkins(int beautyId) {
        checkAndNewBeautyData(beautyId);
        if (!beautyDataMap.containsKey(beautyId)) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_FOUND;
        }
        SkinModule skinModule = player.getModule(SkinModule.class);
        UserMusicRoomBeautyData beautyData = beautyDataMap.get(beautyId);
        List<Integer> skinListByRoleId = SkinMgr.getSkinListByRoleId(eSkinType.Beauty, beautyId);
        List<Integer> allSkinList = new ArrayList<>();
        for (Integer skinId : skinListByRoleId) {
            UserSkin userSkin = skinModule.getUserSkin(skinId);
            if (userSkin == null) {
                continue;
            }
            allSkinList.add(skinId);
        }
        beautyData.setUnlockSkins(allSkinList);

        syncBeautyData(Collections.singletonList(beautyData));

        MusicRoomProto.MusicRoomBeautyUnlockSkinsRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBeautyUnlockSkinsRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setBeautyId(beautyId);
        respMsg.addAllUnlockSkin(allSkinList);
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BEAUTY_UNLOCK_SKINS, respMsg);

        return 0;
    }

    /**
     * 妙音坊 美女使用经验书
     */
    public int beautyUpgrade(int beautyId, int lvUpNum, boolean isTogether) {
        checkAndNewBeautyData(beautyId);
        if (!beautyDataMap.containsKey(beautyId)) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_FOUND;
        }
        if (lvUpNum <= 0) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_LV_UP_NUM_ERROR;
        }

        UserMusicRoomBeautyData beautyData = beautyDataMap.get(beautyId);
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
        if (beautyInfo == null) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
        if (userBeauty == null) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        int upgradeType = GameConfig.MUSIC_ROOM_SKILL_UPGRADE_TYPE_ID_BEAUTY;

        SkillUpgradeInfo nextSkillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, beautyData.getLevel() + 1);
        if (nextSkillUpgradeInfo == null) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_LV_MAX;
        }

        List<GoodsInfo> allExpBookInfoList = GoodsMgr.getGoodsListByType(eGoodsType.MusicRoomBeautyExp.getValue());
        List<GoodsInfo> occupationExpBookInfoList = new ArrayList<>();
        Property expBookHave = new Property();
        for (GoodsInfo goodsInfo : allExpBookInfoList) {
            long bookCountHave = player.getModule(BagModule.class).getUserBagItemCount(goodsInfo.getGoodsId());
            if (goodsInfo.getParamList().get(0).intValue() == beautyInfo.getOccupation()) {
                expBookHave.addProperty(goodsInfo.getGoodsId(), bookCountHave);
                occupationExpBookInfoList.add(goodsInfo);
            }
        }

        int startLv = beautyData.getLevel();
        int endLv = startLv + lvUpNum;
        long expHave = beautyData.getExp();
        long totalExpAdd = 0;
        Property cost = new Property();
        int realEndLv = 1;
        for (int lv = 1; lv < endLv; lv++) {
            SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, lv);
            if (skillUpgradeInfo == null) {
                break;
            }
            if (expHave >= skillUpgradeInfo.getConsumeCount()) {
                expHave -= skillUpgradeInfo.getConsumeCount();
                realEndLv = lv + 1;
                continue;
            }
            long expNeed = skillUpgradeInfo.getConsumeCount() - expHave;
            expHave = 0;

            long expAdd = 0;
            for (GoodsInfo goodsInfo : occupationExpBookInfoList) {
                long bookCountHave = expBookHave.getCountByGoodsId(goodsInfo.getGoodsId()).longValue();
                long bookExp = goodsInfo.getParamList().get(1).longValue();
                long bookCountNeed = (expNeed + bookExp - 1) / bookExp;//向上取整
                long bookCountUse = 0;
                if (bookCountNeed > bookCountHave) {
                    bookCountUse = bookCountHave;
                } else {
                    bookCountUse = bookCountNeed;
                }
                if (bookCountUse == 0) {
                    continue;
                }
                expNeed -= bookCountUse * bookExp;
                expAdd += bookCountUse * bookExp;
                cost.addProperty(goodsInfo.getGoodsId(), bookCountUse);
                expBookHave.removeProperty(goodsInfo.getGoodsId(), BigInteger.valueOf(bookCountUse));

                if (expNeed <= 0) {
                    break;
                }
            }
            totalExpAdd += expAdd;
            if (expNeed <= 0) {
                realEndLv = lv + 1;
            }
            if (expAdd == 0) {
                break;
            }
        }

        if (realEndLv == beautyData.getLevel()) {//不够升1级触发一下
            player.notifyListener(eGamePlayerEventType.RechargeMusicRoom.getValue(), 0);
        }

        if (!cost.isNothing()) {
            if (!player.getModule(CurrencyModule.class).removeCurrency(cost, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomBeautyUpgrade)) {
                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
            }
        } else {
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        beautyData.setExp(beautyData.getExp() + totalExpAdd);
        beautyData.setLevel(realEndLv);
        beautyData.setModifyTime(System.currentTimeMillis());

        //更新属性
        MusicRoomConfigMgr.calcAndSetBeautyAttr(beautyData, beautyInfo, userBeauty.getQuality());

        List<UserMusicRoomBeautyData> changeList = new ArrayList<>();
        changeList.add(beautyData);

        if (!cost.isNothing()) {
            AutoLogMgr.add(new LogMusicRoomBeautyUpgrade(getUserId(), beautyId, beautyData.getLevel(), beautyData.getExp(), PropertyHelper.parsePropertyToString(cost)));
        }

        if (isTogether) {//同步升级,把同职业的其他美女也取出来升级
            List<UserMusicRoomBeautyData> livingBeautyList = getLivingBeautyList(beautyId);
            for (UserMusicRoomBeautyData otherBeautyData : livingBeautyList) {
                BeautyInfo otherBeautyInfo = BeautyMgr.getBeautyInfo(otherBeautyData.getBeautyId());
                if (otherBeautyInfo == null) {
                    continue;
                }
                if (otherBeautyInfo.getOccupation() != beautyInfo.getOccupation()) {
                    continue;
                }

                UserBeauty otherUserBeauty = player.getModule(BeautyModule.class).getUserBeauty(otherBeautyData.getBeautyId());
                if (otherUserBeauty == null) {
                    continue;
                }

                SkillUpgradeInfo otherNextSkillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, otherBeautyData.getLevel() + 1);
                if (otherNextSkillUpgradeInfo == null) {
                    continue;
                }

                int otherStartLv = otherBeautyData.getLevel();
                int otherEndLv = otherStartLv + lvUpNum;
                long otherExpHave = otherBeautyData.getExp();
                long otherTotalExpAdd = 0;
                Property otherCost = new Property();
                int otherRealEndLv = 1;
                for (int lv = 1; lv < otherEndLv; lv++) {
                    SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(upgradeType, lv);
                    if (skillUpgradeInfo == null) {
                        break;
                    }
                    if (otherExpHave >= skillUpgradeInfo.getConsumeCount()) {
                        otherExpHave -= skillUpgradeInfo.getConsumeCount();
                        otherRealEndLv = lv + 1;
                        continue;
                    }
                    long expNeed = skillUpgradeInfo.getConsumeCount() - otherExpHave;
                    otherExpHave = 0;

                    long expAdd = 0;
                    for (GoodsInfo goodsInfo : occupationExpBookInfoList) {
                        long bookCountHave = expBookHave.getCountByGoodsId(goodsInfo.getGoodsId()).longValue();
                        long bookExp = goodsInfo.getParamList().get(1).longValue();
                        long bookCountNeed = (expNeed + bookExp - 1) / bookExp;//向上取整
                        long bookCountUse = 0;
                        if (bookCountNeed > bookCountHave) {
                            bookCountUse = bookCountHave;
                        } else {
                            bookCountUse = bookCountNeed;
                        }
                        if (bookCountUse == 0) {
                            continue;
                        }
                        expNeed -= bookCountUse * bookExp;
                        expAdd += bookCountUse * bookExp;
                        otherCost.addProperty(goodsInfo.getGoodsId(), bookCountUse);
                        expBookHave.removeProperty(goodsInfo.getGoodsId(), BigInteger.valueOf(bookCountUse));

                        if (expNeed <= 0) {
                            break;
                        }
                    }
                    otherTotalExpAdd += expAdd;
                    if (expNeed <= 0) {
                        otherRealEndLv = lv + 1;
                    }
                    if (expAdd == 0) {
                        break;
                    }
                }

                if (!otherCost.isNothing()) {
                    if (!player.getModule(CurrencyModule.class).removeCurrency(otherCost, eLogMoneyType.MusicRoom, eLogMoneyType.MusicRoomBeautyUpgrade)) {
                        break;
                    }
                    cost.addProperty(otherCost);
                } else {
                    break;
                }

                otherBeautyData.setExp(otherBeautyData.getExp() + otherTotalExpAdd);
                otherBeautyData.setLevel(otherRealEndLv);
                otherBeautyData.setModifyTime(System.currentTimeMillis());

                MusicRoomConfigMgr.calcAndSetBeautyAttr(otherBeautyData, otherBeautyInfo, otherUserBeauty.getQuality());

                changeList.add(otherBeautyData);
            }
        }
        MusicRoomProto.MusicRoomBeautyUpgradeRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBeautyUpgradeRespMsg.newBuilder();
        respMsg.setRet(0);
        for (UserMusicRoomBeautyData userMusicRoomBeautyData : changeList) {
            respMsg.addBeautyData(MusicRoomPb.parseBeautyTemp(userMusicRoomBeautyData));
        }
        respMsg.setCost(PropertyHelper.parsePropertyToString(cost));
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BEAUTY_UP, respMsg);

        //        syncBeautyData(changeList);
        return 0;
    }

    public UserMusicRoomBeautyData initBeautyData(int beautyId, BeautyInfo beautyInfo, UserBeauty userBeauty) {
        UserMusicRoomBeautyData beautyData = new UserMusicRoomBeautyData(getUserId(), beautyId);
        MusicRoomConfigMgr.calcAndSetBeautyAttr(beautyData, beautyInfo, userBeauty.getQuality());
        beautyData.setComfort(beautyData.getTotalComfort());
        beautyData.setMood(beautyData.getTotalMood());
        beautyData.setSatiety(beautyData.getTotalSatiety());
        return beautyData;
    }

    private void addNewBeautyData(int beautyId, BeautyInfo beautyInfo, UserBeauty userBeauty) {
        if (!beautyDataMap.containsKey(beautyId)) {
            UserMusicRoomBeautyData beautyData = initBeautyData(beautyId, beautyInfo, userBeauty);
            synchronized (beautyDataMap) {
                beautyDataMap.put(beautyId, beautyData);
            }
        }
    }

    public void checkAndNewBeautyData(int beautyId) {
        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
        if (beautyInfo == null) {
            return;
        }
        UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
        if (!beautyDataMap.containsKey(beautyId)) {
            addNewBeautyData(beautyId, beautyInfo, userBeauty);
        }
    }

    public void cancelRouting(UserMusicRoomBeautyData beautyData) {
        if (beautyData.getLiveInBuildId() != 0) {
            int beforeBuildId = beautyData.getLiveInBuildId();
            UserMusicRoomBuildingData nowBuildingData = buildingDataMap.get(beautyData.getNowBuildingId());
            if (nowBuildingData != null) {
                nowBuildingData.removeNowBeautyId(beautyData.getBeautyId());
            }
            UserMusicRoomBuildingData nextBuildingData = buildingDataMap.get(beautyData.getNextBuildingId());
            if (nextBuildingData != null) {
                nextBuildingData.removeWaitBeautyId(beautyData.getBeautyId());
            }
            AutoLogMgr.add(new LogMusicRoomBeautyCheckIn(getUserId(), beautyData.getBeautyId(), beforeBuildId, 0));
        }
        beautyData.resetRouting();
    }

    /**
     * 妙音坊 美女入住
     * 已入住的,可以换到其他宿舍。先取消自己的行程，再入住
     * 入住的地方有人，先取消那个人的行程，再入住
     * 入住的人有宿舍，宿舍里已经有人，要交换宿舍
     */
    public int beautyCheckIn(int buildId, int beautyId, boolean isReplaceLevel) {
        calcBeautyRouting();
        UserMusicRoomBuildingData userBuildingData = buildingDataMap.get(buildId);
        if (userBuildingData == null) {
            return GameErrorCode.E_MUSIC_ROOM_BUILDING_NOT_UNLOCK;
        }

        if (!MusicRoomConfigMgr.checkBuildingTypeRight(buildId, eMusicRoomBuildingType.Dormitory) &&
                !MusicRoomConfigMgr.checkBuildingTypeRight(buildId, eMusicRoomBuildingType.SeniorDormitory)) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_LIVE_IN_BUILDING_ERR;
        }

        UserBeauty userBeauty = player.getModule(BeautyModule.class).getUserBeauty(beautyId);
        if (userBeauty == null) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyId);
        if (beautyInfo == null) {
            return GameErrorCode.E_BEAUTY_NO_FOUND;
        }

        addNewBeautyData(beautyId, beautyInfo, userBeauty);

        UserMusicRoomBeautyData beautyData = beautyDataMap.get(beautyId);
        if (beautyData.getLiveInBuildId() > 0) {//已入住
            if (beautyData.getLiveInBuildId() == buildId) {
                return GameErrorCode.E_MUSIC_ROOM_BEAUTY_LIVE_IN;
            }

            //有冲榜活动不能被替换
            if (player.getModule(MusicRoomRankActivityModule.class).checkBeautyWasJoin(beautyData.getBeautyId())) {
                return GameErrorCode.E_MUSIC_ROOM_RANK_CAN_NOT_REPLACE_CHECK_IN;
            }
        }

        List<UserMusicRoomBeautyData> needSyncList = new ArrayList<>();
        needSyncList.add(beautyData);

        //默认一个宿舍只能住一个,有人要替换
        UserMusicRoomBeautyData swapBeautyData = null;
        for (UserMusicRoomBeautyData checkBeautyData : beautyDataMap.values()) {
            if (checkBeautyData.getBeautyId() == beautyId) {
                continue;
            }
            if (checkBeautyData.getLiveInBuildId() == buildId) {
                //有冲榜活动不能被替换
                if (player.getModule(MusicRoomRankActivityModule.class).checkBeautyWasJoin(checkBeautyData.getBeautyId())) {
                    return GameErrorCode.E_MUSIC_ROOM_RANK_CAN_NOT_REPLACE_CHECK_IN;
                }

                //新逻辑同职业的替换入住要同时替换等级和经验,替换后重新计算属性
                BeautyInfo swapBeautyInfo = BeautyMgr.getBeautyInfo(checkBeautyData.getBeautyId());
                if (swapBeautyInfo == null) {
                    return GameErrorCode.E_BEAUTY_NO_FOUND;
                }
                UserBeauty swapUserBeauty = player.getModule(BeautyModule.class).getUserBeauty(checkBeautyData.getBeautyId());
                if (userBeauty == null) {
                    return GameErrorCode.E_BEAUTY_NO_FOUND;
                }


                if (swapBeautyInfo.getOccupation() == beautyInfo.getOccupation() && isReplaceLevel) {
                    int swapLv = checkBeautyData.getLevel();
                    long swapExp = checkBeautyData.getExp();

                    checkBeautyData.setLevel(beautyData.getLevel());
                    checkBeautyData.setExp(beautyData.getExp());

                    beautyData.setLevel(swapLv);
                    beautyData.setExp(swapExp);

                    //更新属性
                    MusicRoomConfigMgr.calcAndSetBeautyAttr(beautyData, beautyInfo, userBeauty.getQuality());
                    MusicRoomConfigMgr.calcAndSetBeautyAttr(checkBeautyData, swapBeautyInfo, swapUserBeauty.getQuality());

                    AutoLogMgr.add(new LogMusicRoomBeautyUpgrade(getUserId(), beautyData.getBeautyId(), beautyData.getLevel(), beautyData.getExp(), ""));
                    AutoLogMgr.add(new LogMusicRoomBeautyUpgrade(getUserId(), checkBeautyData.getBeautyId(), checkBeautyData.getLevel(), checkBeautyData.getExp(), ""));
                }

                //替换,入住的建筑有人入住了,取消原来的人的行程
                cancelRouting(checkBeautyData);
                swapBeautyData = checkBeautyData;
                if (checkBeautyData.getBeautyId() != beautyId) {
                    needSyncList.add(checkBeautyData);
                }
                break;
            }
        }
        int beforeBuildId = beautyData.getLiveInBuildId();

        //入住的属性变化处理
        beautyCheckInChange(beautyData, buildId);

        if (swapBeautyData != null && beforeBuildId != 0) {//交换宿舍
            beautyCheckInChange(swapBeautyData, beforeBuildId);
        }

        syncBeautyData(needSyncList);

        MusicRoomProto.MusicRoomBeautyCheckInRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBeautyCheckInRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.addAllRouting(MusicRoomPb.parseBeautyRoutingTempList(new ArrayList<>(beautyDataMap.values())));

        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BEAUTY_CHECK_IN, respMsg);

        AutoLogMgr.add(new LogMusicRoomBeautyCheckIn(getUserId(), beautyId, beforeBuildId, buildId));

        resetOneDayByHour();//入住时如果没有满意度,生成一下
        return 0;
    }

    public void beautyCheckInChange(UserMusicRoomBeautyData beautyData, int buildId) {
        beautyData.setLiveInBuildId(buildId);
        beautyData.setLiveInTime(System.currentTimeMillis());
        beautyData.setLastTimerEndTime(MusicRoomConfigMgr.getNowTimeNumberStartTime());

        beautyData.setScheduleListType(0);
        List<Integer> newScheduleList = MusicRoomConfigMgr.getLifeScheduleList();
        beautyData.setScheduleList(newScheduleList);

        //入住后属性从0开始
//        beautyData.setComfort(0);
//        beautyData.setMood(0);
//        beautyData.setSatiety(0);

//        if (isForceChangeToLifeRouting || beautyData.isAnyOneAttrPercentLessThan(GameConfig.MUSIC_ROOM_SCHEDULE_LIFE_EXCHANGE_COND)) {
//            //美女的三项属性有任一项<20%,则更新为生活行程
//            beautyData.setScheduleListType(1);
//            List<Integer> newScheduleList = MusicRoomConfigMgr.getLifeScheduleList();
//            beautyData.setScheduleList(newScheduleList);
//        } else {
//            beautyData.setScheduleListType(2);
//            List<Integer> newScheduleList = MusicRoomConfigMgr.randomStudyWorkScheduleList();
//            beautyData.setScheduleList(newScheduleList);
//        }
        //入住时默认入住宿舍
        UserMusicRoomBuildingData buildingData = buildingDataMap.get(beautyData.getLiveInBuildId());
        beautyData.setNowBuildingId(buildingData.getBuildId());
        buildingData.addNowBeautyId(beautyData.getBeautyId());
        //找下一个行程的建筑
        int nextScheduleType = beautyData.getSchedule(MusicRoomConfigMgr.getNowTimeNumber() + 1);
        UserMusicRoomBuildingData nextBuildingData = MusicRoomConfigMgr.searchBuildingByScheduleType(getBuildingDataSortList(nextScheduleType), nextScheduleType, true);
        if (nextBuildingData == null) {
            nextBuildingData = buildingDataMap.get(beautyData.getLiveInBuildId());
        }
        beautyData.setNextBuildingId(nextBuildingData.getBuildId());
        nextBuildingData.addWaitCheckInBeautyId(beautyData.getBeautyId());
        beautyData.setModifyTime(System.currentTimeMillis());
    }

    public List<UserMusicRoomBuildingData> getBuildingDataSortList(int scheduleType) {
        List<UserMusicRoomBuildingData> buildingDataSortList = new ArrayList<>();
        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            MusicRoomBuildBaseConfig buildBaseConfig = MusicRoomConfigMgr.getBuildBaseConfig(buildingData.getBuildId());
            if (buildBaseConfig.getScheduleType() == scheduleType) {
                buildingDataSortList.add(buildingData);
            }
        }

        //按照建筑家具总等级排序，等级高的优先，等级相同的按照建筑id排序
        buildingDataSortList.sort((o1, o2) -> {
            int compare = Integer.compare(o2.getTotalFurnitureLevel(), o1.getTotalFurnitureLevel());
            if (compare == 0) {
                return Integer.compare(o1.getBuildId(), o2.getBuildId());
            }
            return compare;
        });
        return buildingDataSortList;
    }

    /**
     * 徽章升级
     */
    public int badgeUpgrade() {
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        long badgeLevel = attributeModule.getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        long totalExp = attributeModule.getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);

        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), (int) badgeLevel);
        if (badgeConfig == null) {
            return GameErrorCode.E_MUSIC_ROOM_CONFIG_ERROR;
        }

        BadgeConfig nextBadgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), (int) badgeLevel + 1);
        if (nextBadgeConfig == null) {
            return GameErrorCode.E_MUSIC_ROOM_BADGE_LV_MAX;
        }

        if (totalExp < badgeConfig.getUnlockValue()) {
            return GameErrorCode.E_MUSIC_ROOM_BADGE_LV_UP_EXP_NOT_ENOUGH;
        }

        //升级前,先累计徽章的时辰产出,需求改了,注释
//        Property amountReward = calcBadgeTimerAmountReward();
//        if (!amountReward.isNothing()) {
//            player.getModule(PlayerModule.class).getUserHistoryAttribute().addMusicRoomTimerAmountReward(amountReward);
//            long lastRewardTimeNew = MusicRoomConfigMgr.getNextTimeNumberTime() - GameConfig.MUSIC_ROOM_HOUR_REALITY_TIME * DateHelper.SECOND_MILLIONS;
//            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MusicRoomLastTimerRewardTime, lastRewardTimeNew);
//        }

        attributeModule.setAttribute(ePlayerAttrType.MusicRoomBadgeLevel, badgeLevel + 1);

        //赚速变更
        player.getModule(EarnSpeedModule.class).scheduleAddSilver();

        MusicRoomProto.MusicRoomBadgeUpgradeRespMsg.Builder respMsg = MusicRoomProto.MusicRoomBadgeUpgradeRespMsg.newBuilder();
        respMsg.setRet(0);
        respMsg.setNewLevel((int) badgeLevel + 1);
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_BADGE_UP, respMsg);

        if (nextBadgeConfig != null) {
            player.getModule(BadgeModule.class).addBadge(nextBadgeConfig.getId(), eBadgeType.MusicRoom.getValue());
        }

        MusicRoomLog.trackUserData(player);

        long totalProsperity = attributeModule.getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);
        RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(totalProsperity), eRankType.MusicRoomRank.getValue(), String.valueOf(badgeLevel + 1));
        return 0;
    }

    public Map<Integer, UserMusicRoomBuildingData> getBuildingDataMap() {
        return buildingDataMap;
    }

    public Map<Integer, UserMusicRoomBeautyData> getBeautyDataMap() {
        return beautyDataMap;
    }

    /**
     * 加门客精进技能上限,目前需修改了没配置,留着,如果配了就会生效
     * @return
     */
    public int getStageSkillMaxLevelAdd() {
        int addValue = 0;
        if (!SystemOpenMgr.systemOpen(player, eSystemId.BadgeShow.getValue()) || !SystemOpenMgr.systemOpen(player, eSystemId.MusicRoom.getValue())) {
            return addValue;
        }

        int badgeLevel = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), badgeLevel);
        if (badgeConfig == null) {
            return addValue;
        }
        for (Integer skillId : badgeConfig.getSkillIdList()) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo != null && skillInfo.getType() == eSkillType.FishPondStageSkillMaxLevelAdd.getValue()) {
                addValue += SkillMgr.getSkillAddition(skillInfo, badgeLevel);
            }
        }
        return addValue;
    }

    /**
     * 加门客初始技能上限
     * @return
     */
    public int getSkillMaxLevelAdd() {
        int addValue = 0;

        if (!SystemOpenMgr.systemOpen(player, eSystemId.MusicRoom.getValue())) {
            return addValue;
        }

        int badgeLevel = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), badgeLevel);
        if (badgeConfig == null) {
            return addValue;
        }
        for (Integer skillId : badgeConfig.getSkillIdList()) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo != null && skillInfo.getType() == eSkillType.SkillMaxLevelAdd.getValue()) {
                addValue += SkillMgr.getSkillAddition(skillInfo, badgeLevel);
            }
        }
        return addValue;
    }

    public List<UserMusicRoomBeautyData> getLivingBeautyList() {
        List<UserMusicRoomBeautyData> beautyDataList = new ArrayList<>();
        for (UserMusicRoomBeautyData beautyData : beautyDataMap.values()) {
            if (beautyData.getLiveInBuildId() == 0) {
                continue;
            }

            beautyDataList.add(beautyData);
        }
        return beautyDataList;
    }

    public List<UserMusicRoomBeautyData> getLivingBeautyList(int excludeBeautyId) {
        List<UserMusicRoomBeautyData> beautyDataList = new ArrayList<>();
        for (UserMusicRoomBeautyData beautyData : beautyDataMap.values()) {
            if (beautyData.getLiveInBuildId() == 0) {
                continue;
            }

            if (beautyData.getBeautyId() == excludeBeautyId) {
                continue;
            }

            beautyDataList.add(beautyData);
        }
        return beautyDataList;
    }

    public List<UserMusicRoomBeautyData> getSortLivingBeautyList() {
        List<UserMusicRoomBeautyData> beautyDataList = getLivingBeautyList();
        if (beautyDataList.isEmpty()) {
            return beautyDataList;
        }

        //没有产出需求，不用排序了
//        //经验高的排前面
//        beautyDataList.sort((o1, o2) -> {
//            int compare = Long.compare(o2.getExp(), o1.getExp());
//            if (compare == 0) {
//                compare = Integer.compare(o1.getBeautyId(), o2.getBeautyId());
//            }
//            return compare;
//        });
        return beautyDataList;
    }

    /**
     * 获得12时辰后的结果预览
     */
    public int getAfterTwelveTimerResult() {
        calcBeautyRouting();
        int badgeLevel = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomBadgeLevel);
        BadgeConfig badgeConfig = BadgeConfigMgr.getBadgeConfigByLevel(eBadgeType.MusicRoom.getValue(), badgeLevel);
        if (badgeConfig == null) {
            return GameErrorCode.E_BADGE_NOT_EXIST;
        }

        List<UserMusicRoomBeautyData> beautyDataList = getSortLivingBeautyList();

        if (beautyDataList.isEmpty()) {
            return GameErrorCode.E_MUSIC_ROOM_BEAUTY_NOT_LIVE_IN;
        }

        //计算多少时辰后的结果
        long passTimerAmount = 12;

        //获得美女行程结果
        MusicRoomRoutingResult calcResult = MusicRoomConfigMgr.calcBeautyRouting(beautyDataList, buildingDataMap, (int) passTimerAmount, MusicRoomConfigMgr.getNowTimeNumber());

        MusicRoomProto.MusicRoomResultAfterTwentyTimerRespMsg.Builder respMsg = MusicRoomProto.MusicRoomResultAfterTwentyTimerRespMsg.newBuilder();
        respMsg.setRet(0);
        Property amountReward = calcResult.getAmountReward();
        Property timerProduce = PropertyHelper.parseStringToProperty(badgeConfig.getSpecialEffect());
        timerProduce.goodCountMultiNum(passTimerAmount);
        amountReward.addProperty(timerProduce);

        respMsg.setReward(PropertyHelper.parsePropertyToString(amountReward));

        for (MusicRoomRoutingBeauty routingBeauty : calcResult.getBeautyMap().values()) {
            MusicRoomProto.MusicRoomBeautyResultTemp.Builder builder = MusicRoomProto.MusicRoomBeautyResultTemp.newBuilder();
            builder.setBeautyId(routingBeauty.getBeautyId());
            builder.setComfort(routingBeauty.getComfort());
            builder.setMood(routingBeauty.getMood());
            builder.setSatiety(routingBeauty.getSatiety());
            respMsg.addBeautyResult(builder);
        }

        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_RESULT_AFTER_TWELVE_TIMER, respMsg);

        return 0;
    }

    /**
     * 计算时辰卡奖励
     */
    public Property calcTimerCardReward(long timerAmount) {
        Property totalReward = new Property();
        /**
         * 策划改了,直接所有建筑拉一起产出
         */
        List<UserMusicRoomBuildingData> buildingDataList = new ArrayList<>(buildingDataMap.values());
        Property totalBuildingReward = new Property();
        Property totalSupportMoney = new Property();
        for (UserMusicRoomBuildingData buildingData : buildingDataList) {
            Property buildingReward = new Property();
            Property supportMoney = new Property(GameConfig.MUSIC_ROOM_SUPPORT_GOODS_ID, buildingData.getSupportMoneyAmount() * timerAmount);
            totalSupportMoney.addProperty(supportMoney);
            for (int i = 0; i < timerAmount; i++) {
                Property expBookProduce = PropertyHelper.randomPropertyByListList(buildingData.getProduceExpBookList());
                Property supportProduce = PropertyHelper.randomPropertyByListList(buildingData.getProduceSupportItemList());
                buildingReward.addProperty(expBookProduce);
                buildingReward.addProperty(supportProduce);
            }
            totalBuildingReward.addProperty(buildingReward);
        }
        totalSupportMoney.goodMulti(getGoodAppraiseBigDecimalAddition(), BigDecimal.ROUND_DOWN);

        totalReward.addProperty(totalBuildingReward);
        totalReward.addProperty(totalSupportMoney);

        return totalReward;
    }

    public UserMusicRoomBeautyData getBeautyData(int beautyId) {
        return beautyDataMap.get(beautyId);
    }

    public int getFurnitureLevel(int buildId, int furnitureKindId) {
        UserMusicRoomBuildingData buildingData = buildingDataMap.get(buildId);
        if (buildingData == null) {
            return 0;
        }
        int furnitureId = MusicRoomConfigMgr.getFurnitureIdByKindId(furnitureKindId);
        MusicRoomFurnitureInfo furnitureInfo = buildingData.getFurnitureInfo(furnitureId);
        if (furnitureInfo == null) {
            return 0;
        }
        return furnitureInfo.getLevel();
    }

    public int getFurnitureLevelById(int buildId, int furnitureId) {
        UserMusicRoomBuildingData buildingData = buildingDataMap.get(buildId);
        if (buildingData == null) {
            return 0;
        }
        MusicRoomFurnitureInfo furnitureInfo = buildingData.getFurnitureInfo(furnitureId);
        if (furnitureInfo == null) {
            return 0;
        }
        return furnitureInfo.getLevel();
    }

    public void refreshBeautyAttr(UserBeauty userBeauty) {
        UserMusicRoomBeautyData beautyData = getBeautyData(userBeauty.getBeautyId());
        if (beautyData == null) {
            return;
        }

        BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(beautyData.getBeautyId());
        if (beautyInfo == null) {
            return;
        }

        MusicRoomConfigMgr.calcAndSetBeautyAttr(beautyData, beautyInfo, userBeauty.getQuality());
        syncBeautyData(Collections.singletonList(beautyData));
    }

    /**
     * 获得每个时间单位产出的应援币
     *
     * @return
     */
    public long getRewardSupportGoodsPerTime() {
        long result = 0;
        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            result += buildingData.getSupportMoneyAmount();
        }
        return result;
    }

    public void syncAppraiseList(List<UserMusicRoomAppraiseData> list) {
        List<MusicRoomProto.MusicRoomAppraiseTemp> musicRoomAppraiseTemps = MusicRoomPb.paresAppraiseTempList(list);
        MusicRoomProto.MusicRoomAppraiseSyncMsg.Builder syncMsg = MusicRoomProto.MusicRoomAppraiseSyncMsg.newBuilder();
        syncMsg.addAllAppraiseData(musicRoomAppraiseTemps);
        player.sendPacket(ClientProtocol.U_MUSIC_ROOM_APPRAISE_SYNC, syncMsg);
    }

    /**
     * 刷新评价列表,首次和跨天才刷新
     */
    public void refreshAppraiseList() {
        long totalProsperity = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);
        MusicRoomFurnitureConfig levelConfig = MusicRoomConfigMgr.getFurnitureConfigByProsperity(totalProsperity);
        if (levelConfig == null) {
            return;
        }

        //入住美女
        List<UserMusicRoomBeautyData> livingBeautyList = getLivingBeautyList();
        if (livingBeautyList.isEmpty()) {
            return;
        }

        //有入住的宿舍 建筑id-美女id
        Map<Integer, Integer> livingBuildingMap = new HashMap<>();
        for (UserMusicRoomBeautyData beautyData : livingBeautyList) {
            livingBuildingMap.put(beautyData.getLiveInBuildId(), beautyData.getBeautyId());
        }

        List<Integer> goodAppraiseIdList = new ArrayList<>();
        List<Integer> badAppraiseIdList = new ArrayList<>();

        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            int buildType = MusicRoomConfigMgr.getBuildType(buildingData.getBuildId());
            if (buildType == eMusicRoomBuildingType.Dormitory.getValue() || buildType == eMusicRoomBuildingType.SeniorDormitory.getValue()){
                //没入住的宿舍不要加入评价
                if (!livingBuildingMap.containsKey(buildingData.getBuildId())) {
                    continue;
                }
            }

            for (MusicRoomFurnitureInfo furnitureInfo : buildingData.getFurnitureInfos()) {
                int furnitureUniqueId = MusicRoomConfigMgr.getFurnitureUniqueId(buildingData.getBuildId(), furnitureInfo.getId());
                int goodLevel = levelConfig.getStandardGradeLevelNeed(buildingData.getBuildId());
                if (furnitureInfo.getLevel() >= goodLevel) {
                    goodAppraiseIdList.add(furnitureUniqueId);
                } else {
                    badAppraiseIdList.add(furnitureUniqueId);
                }
            }
        }

        int allAppraiseNum = MusicRoomConfigMgr.getAllAppraiseNum();//总评价数
        int goodAppraiseNum = MusicRoomConfigMgr.getGoodAppraiseNum(); //好评数
        int badAppraiseNum = MusicRoomConfigMgr.getBadAppraiseNum(); //差评数

        Map<Integer, Integer> takeIdMap = new HashMap<>();

        //先从差评家具列表里抽
        for (int i = 0; i < badAppraiseNum; i++) {
            if (badAppraiseIdList.isEmpty()) {
                break;
            }
            int index = random.nextInt(badAppraiseIdList.size());
            int furnitureUniqueId = badAppraiseIdList.remove(index);
            takeIdMap.put(furnitureUniqueId, 2);
        }
        //抽好评
        for (int i = 0; i < goodAppraiseNum; i++) {
            if (goodAppraiseIdList.isEmpty()) {
                break;
            }
            int index = random.nextInt(goodAppraiseIdList.size());
            int furnitureUniqueId = goodAppraiseIdList.remove(index);
            takeIdMap.put(furnitureUniqueId, 1);
        }
        List<Integer> remainList = new ArrayList<>();
        remainList.addAll(goodAppraiseIdList);
        remainList.addAll(badAppraiseIdList);
        int remainNum = allAppraiseNum - takeIdMap.size();
        //抽剩下的
        for (int i = 0; i < remainNum; i++) {
            if (remainList.isEmpty()) {
                break;
            }
            int index = random.nextInt(remainList.size());
            int furnitureUniqueId = remainList.remove(index);
            if (goodAppraiseIdList.contains(furnitureUniqueId)) {
                takeIdMap.put(furnitureUniqueId, 1);
            } else {
                takeIdMap.put(furnitureUniqueId, 2);
            }
        }
        long currentTime = DateHelper.getCurrentTime();
        //重置旧的评价
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataMap.values()) {
            appraiseData.resetAppraise();
            appraiseData.setAppraiseTime(currentTime);
        }

        //设置新的评价
        List<Integer> appraiseIdList = new ArrayList<>(appraiseDataMap.keySet());
        List<Integer> waitTakeFurnitureIdList = new ArrayList<>(takeIdMap.keySet());

        List<Integer> rangeList = StringUtils.stringToIntegerList(GameConfig.MUSIC_ROOM_GOOD_TARGET_LEVEL_RANGE, "\\|");
        int randomMin = rangeList.get(0);
        int randomMax = rangeList.get(1);
        int maxLevel = MusicRoomConfigMgr.getFurnitureMaxLevel();

        while (!appraiseIdList.isEmpty() && !waitTakeFurnitureIdList.isEmpty()) {
            Integer appraiseId = appraiseIdList.remove(0);
            Integer furnitureUniqueId = waitTakeFurnitureIdList.remove(0);
            int buildId = MusicRoomConfigMgr.getBuildIdByFurnitureUniqueId(furnitureUniqueId);
            int furnitureId = MusicRoomConfigMgr.getFurnitureIdByFurnitureUniqueId(furnitureUniqueId);
            int appraise = takeIdMap.get(furnitureUniqueId);
            int furnitureLevel = getFurnitureLevelById(buildId, furnitureId);
//            int goodLevel = levelConfig.getStandardGradeLevelNeed(buildId);
            int targetLevel = furnitureLevel;
            if (appraise != 1){//差评才要提升目标等级
                targetLevel = random.nextInt(randomMax - randomMin + 1) + randomMin + furnitureLevel;
                targetLevel = Math.min(targetLevel, maxLevel);
            }

            UserMusicRoomAppraiseData appraiseData = appraiseDataMap.get(appraiseId);
            appraiseData.setBuildId(buildId);
            appraiseData.setFurnitureId(furnitureId);
            appraiseData.setStatus(appraise);
            appraiseData.setAppraiseTime(currentTime);
            appraiseData.setTargetLevel(targetLevel);

            if (livingBuildingMap.containsKey(buildId)) {
                //是宿舍要拿入住这个宿舍的美女
                int beautyId = livingBuildingMap.get(buildId);
                appraiseData.setBeautyId(beautyId);
            } else {
                //随机一个入住美女
                if (!livingBeautyList.isEmpty()) {
                    int index = random.nextInt(livingBeautyList.size());
                    UserMusicRoomBeautyData beautyData = livingBeautyList.get(index);
                    appraiseData.setBeautyId(beautyData.getBeautyId());
                }
            }
        }

        while (!waitTakeFurnitureIdList.isEmpty()) {
            Integer furnitureUniqueId = waitTakeFurnitureIdList.remove(0);
            int buildId = MusicRoomConfigMgr.getBuildIdByFurnitureUniqueId(furnitureUniqueId);
            int furnitureId = MusicRoomConfigMgr.getFurnitureIdByFurnitureUniqueId(furnitureUniqueId);
            int appraise = takeIdMap.get(furnitureUniqueId);
            int furnitureLevel = getFurnitureLevelById(buildId, furnitureId);
//            int goodLevel = levelConfig.getStandardGradeLevelNeed(buildId);
            int targetLevel = furnitureLevel;
            if (appraise != 1){
                targetLevel = random.nextInt(randomMax - randomMin + 1) + randomMin + furnitureLevel;
                targetLevel = Math.min(targetLevel, maxLevel);
            }

            UserMusicRoomAppraiseData appraiseData = new UserMusicRoomAppraiseData(player.getUserId(), maxAppraiseID.getAndIncrement());
            appraiseData.setBuildId(buildId);
            appraiseData.setFurnitureId(furnitureId);
            appraiseData.setStatus(appraise);
            appraiseData.setAppraiseTime(currentTime);
            appraiseData.setTargetLevel(targetLevel);
            if (livingBuildingMap.containsKey(buildId)) {
                //是宿舍要拿入住这个宿舍的美女
                int beautyId = livingBuildingMap.get(buildId);
                appraiseData.setBeautyId(beautyId);
            } else {
                //随机一个入住美女
                if (!livingBeautyList.isEmpty()) {
                    int index = random.nextInt(livingBeautyList.size());
                    UserMusicRoomBeautyData beautyData = livingBeautyList.get(index);
                    appraiseData.setBeautyId(beautyData.getBeautyId());
                }
            }

            synchronized (appraiseDataMap) {
                appraiseDataMap.put(appraiseData.getAppraiseId(), appraiseData);
            }
        }

        syncAppraiseList(new ArrayList<>(appraiseDataMap.values()));
    }

    /**
     * 替换评价列表,繁荣度等级提升时
     */
    public void replaceAppraiseList() {
        int replaceNum = GameConfig.MUSIC_ROOM_GOOD_REVIEWS_RULE_2;
        long totalProsperity = player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MusicRoomTotalProsperity);
        MusicRoomFurnitureConfig levelConfig = MusicRoomConfigMgr.getFurnitureConfigByProsperity(totalProsperity);
        if (levelConfig == null) {
            return;
        }

        //入住美女
        List<UserMusicRoomBeautyData> livingBeautyList = getLivingBeautyList();
        if (livingBeautyList.isEmpty()) {
            return;
        }

        //有入住的宿舍 建筑id-美女id
        Map<Integer, Integer> livingBuildingMap = new HashMap<>();
        for (UserMusicRoomBeautyData beautyData : livingBeautyList) {
            livingBuildingMap.put(beautyData.getLiveInBuildId(), beautyData.getBeautyId());
        }

        //取当前好评和差评的家具 key 家具唯一id
        Map<Integer, UserMusicRoomAppraiseData> goodAppraiseDataMap = new HashMap<>();
        Map<Integer, UserMusicRoomAppraiseData> badAppraiseDataMap = new HashMap<>();
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataMap.values()) {
            int furnitureUniqueId = MusicRoomConfigMgr.getFurnitureUniqueId(appraiseData.getBuildId(), appraiseData.getFurnitureId());
            if (appraiseData.getStatus() == 1) {
                goodAppraiseDataMap.put(furnitureUniqueId, appraiseData);
            } else {
                badAppraiseDataMap.put(furnitureUniqueId, appraiseData);
            }
        }

        List<Integer> badAppraiseFurnitureIdList = new ArrayList<>();

        for (UserMusicRoomBuildingData buildingData : buildingDataMap.values()) {
            int buildType = MusicRoomConfigMgr.getBuildType(buildingData.getBuildId());
            if (buildType == eMusicRoomBuildingType.Dormitory.getValue() || buildType == eMusicRoomBuildingType.SeniorDormitory.getValue()){
                //没入住的宿舍不要加入评价
                if (!livingBuildingMap.containsKey(buildingData.getBuildId())) {
                    continue;
                }
            }

            for (MusicRoomFurnitureInfo furnitureInfo : buildingData.getFurnitureInfos()) {
                int furnitureUniqueId = MusicRoomConfigMgr.getFurnitureUniqueId(buildingData.getBuildId(), furnitureInfo.getId());
                //已经在差评里的不取
                if (badAppraiseDataMap.containsKey(furnitureUniqueId)) {
                    continue;
                }
                int goodLevel = levelConfig.getStandardGradeLevelNeed(buildingData.getBuildId());
                if (furnitureInfo.getLevel() < goodLevel) {
                    badAppraiseFurnitureIdList.add(furnitureUniqueId);
                }
            }
        }

        long currentTime = DateHelper.getCurrentTime();

        //好评替换为差评
        List<UserMusicRoomAppraiseData> replaceAppraiseList = new ArrayList<>();
        if (!badAppraiseFurnitureIdList.isEmpty() && !goodAppraiseDataMap.isEmpty()) {
            for (int i = 0; i < replaceNum; i++) {
                if (badAppraiseFurnitureIdList.isEmpty() || goodAppraiseDataMap.isEmpty()) {
                    break;
                }

                int index2 = random.nextInt(badAppraiseFurnitureIdList.size());
                int furnitureUniqueId = badAppraiseFurnitureIdList.remove(index2);
                int buildId = MusicRoomConfigMgr.getBuildIdByFurnitureUniqueId(furnitureUniqueId);
                int furnitureId = MusicRoomConfigMgr.getFurnitureIdByFurnitureUniqueId(furnitureUniqueId);
                int goodLevel = levelConfig.getStandardGradeLevelNeed(buildId);
                UserMusicRoomAppraiseData appraiseData = null;
                if (goodAppraiseDataMap.containsKey(furnitureUniqueId)) {
                    //升级后好评变差评的家具评价,取出
                    appraiseData = goodAppraiseDataMap.get(furnitureUniqueId);
                    goodAppraiseDataMap.remove(furnitureUniqueId);
                } else {//不在现有评价里的家具,随机一个,取出
                    List<Integer> idList = new ArrayList<>(goodAppraiseDataMap.keySet());
                    int index = random.nextInt(idList.size());
                    int randomFurnitureUniqueId = idList.get(index);
                    appraiseData = goodAppraiseDataMap.get(randomFurnitureUniqueId);
                    goodAppraiseDataMap.remove(randomFurnitureUniqueId);
                }

                appraiseData.setBuildId(buildId);
                appraiseData.setFurnitureId(furnitureId);
                appraiseData.setStatus(2);
                appraiseData.setTargetLevel(goodLevel);
                appraiseData.setAppraiseTime(currentTime);
                replaceAppraiseList.add(appraiseData);
            }
        }

        if (!replaceAppraiseList.isEmpty()) {
            syncAppraiseList(new ArrayList<>(appraiseDataMap.values()));
        }
    }

    public UserMusicRoomAppraiseData findAppraiseDataByFurnitureId(int buildId, int furnitureId) {
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataMap.values()) {
            if (appraiseData.getBuildId() == buildId && appraiseData.getFurnitureId() == furnitureId) {
                return appraiseData;
            }
        }
        return null;
    }

    public void resetOneDayByHour() {
        if (appraiseDataMap.isEmpty()){
            refreshAppraiseList();
        } else {
            long currentTime = DateHelper.getCurrentTime();
            long todayZeroTimeStamp = DateHelper.getZeroTimeStamp(currentTime);
            long resetTime = todayZeroTimeStamp + GameConfig.MUSIC_ROOM_APPRAISE_RESET_DAY_HOUR * DateHelper.HOUR_MILLIONS;
            for (UserMusicRoomAppraiseData appraiseData : appraiseDataMap.values()) {
                if (appraiseData.getAppraiseTime() < resetTime && currentTime >= resetTime) {
                    refreshAppraiseList();
                    break;
                }
            }
        }
    }

    public MusicRoomTimerAmountResult calcTotalTimerReward() {
        return calcBuildingAmountReward();
    }

    public int getGoodAppraiseAddition() {
        int goodNum = 0;
        int totalNum = 0;
        for (UserMusicRoomAppraiseData appraiseData : appraiseDataMap.values()) {
            if (appraiseData.getBeautyId() != 0) {
                totalNum++;
                if (appraiseData.getStatus() == 1 || appraiseData.getNewStatus() == 1) {
                    goodNum++;
                }
            }
        }
        return MusicRoomConfigMgr.getGoodAppraiseAddition(goodNum, totalNum);
    }

    public BigDecimal getGoodAppraiseBigDecimalAddition() {
        BigDecimal addition = BigDecimal.valueOf(getGoodAppraiseAddition()).divide(BigDecimal.valueOf(1000)).add(BigDecimal.ONE);
        return addition;
    }

}
